/********************************************************************************
* @file    bsp_tim.c
* @author  jianqiang.xue
* @version V1.1.0
* @date    2023-02-26
* @brief   本文件不再初始化GPIO，由APP_IO完成引脚初始化和复用。
********************************************************************************/
/* Public Includes ------------------------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "RTE_Components.h"
#include CMSIS_device_header

#include "cx32l003_hal_basetim.h"

#include "bsp_gpio.h"
#include "bsp_tim.h"

/* Private Includes ----------------------------------------------------------*/
#include "ls_gpio.h"
#include "ls_syscfg.h"

#include "log.h"
/* Private Define ------------------------------------------------------------*/
#ifndef LS_APP_IO_CHANGE_SUPPORT
#define IO_TYPE(io)  (g_io_cfg[io].type)
#else // 支持可变
#include "app_io.h"
#define IO_TYPE(io)  (g_io_cfg[io].type)
#endif
/* Private Typedef -----------------------------------------------------------*/
#if LS_TIM1_EN
TIM_HandleTypeDef *g_tim1_handle = NULL;
TIM_OC_InitTypeDef *g_tim1_oc_handle = NULL;
bsp_tim_cfg_t g_tim1_cfg = {
    .prescaler = LS_TIM1_PRESCALER, .period = LS_TIM1_PERIOD, .level_logic = LS_TIM1_LEVEL_LOGIC
};
#endif
#if LS_TIM2_EN
TIM_HandleTypeDef *g_tim2_handle = NULL;
TIM_OC_InitTypeDef *g_tim2_oc_handle = NULL;
bsp_tim_cfg_t g_tim2_cfg = {
    .prescaler = LS_TIM2_PRESCALER, .period = LS_TIM2_PERIOD, .level_logic = LS_TIM2_LEVEL_LOGIC
};
#endif

#if LS_TIM10_EN
BASETIM_HandleTypeDef *g_tim10_handle = NULL;
static uint8_t g_tim10_pwm_update_cnt = 0;
static bsp_base_tim_cfg_t *g_tim10_cfg = NULL;
#endif
#if LS_TIM11_EN
BASETIM_HandleTypeDef *g_tim11_handle = NULL;
static uint8_t g_tim11_pwm_update_cnt = 0;
static bsp_base_tim_cfg_t *g_tim11_cfg = NULL;
#endif
/* Private function  ---------------------------------------------------------*/
/**
 * @brief  初始化tim_ch引脚
 * @param  io: 引脚号
 * @param  arf: 复用值
 */
static inline void io_cfg_as_tim(uint8_t io, uint8_t arf) {
    if (io == 0 || (io > LS_IO_NUM - 1)) return;
    GPIO_InitTypeDef GPIO_InitStruct = {
        .Pin             = g_io_cfg[io].io.pin,
        .Mode            = GPIO_MODE_AF,           // 【GPIO端口复用功能】
        .OpenDrain       = GPIO_PUSHPULL,          // 推免输出
        .Debounce.Enable = GPIO_DEBOUNCE_DISABLE,  // 禁止输入去抖动
        .SlewRate        = GPIO_SLEW_RATE_HIGH,    // 电压转换速率
        .DrvStrength     = GPIO_DRV_STRENGTH_HIGH, // 驱动强度
        .Pull            = GPIO_PULLUP,            // 上拉
        .Alternate       = arf
    };
    SET_BIT(RCC->HCLKEN, g_io_cfg[io].io.periph);
    HAL_GPIO_Init(g_io_cfg[io].io.port, (GPIO_InitTypeDef*)&GPIO_InitStruct);
}

/* Public function prototypes -----------------------------------------------*/
#if LS_TIM1_EN
uint8_t bsp_tim1_pwm_init(bsp_tim_cfg_t *cfg) {
    if (g_tim1_handle) return 0; // 已经初始化过
    if (cfg == NULL) return 3; // 配置为空
    g_tim1_handle = malloc(sizeof(TIM_HandleTypeDef)); // 申请空间
    if (!g_tim1_handle) return 1; // TIM结构体无法申请空间
    g_tim1_oc_handle = malloc(sizeof(TIM_OC_InitTypeDef)); // 申请空间
    if (!g_tim1_oc_handle) {
        free(g_tim1_handle);
        return 2; // TIM类型结构体无法申请空间
    }
    // 结构体赋值
    g_tim1_handle->Instance               = TIM1;
    g_tim1_handle->Init.ClockDivision     = 0;                              // CKD 时钟分频因子(Clock division)
    g_tim1_handle->Init.RepetitionCounter = 0;                              // TIM1_RCR 重复计数器的值
    g_tim1_handle->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 禁止自动重装载

    g_tim1_handle->Init.Period            = cfg->period;      // 重装载值
    g_tim1_handle->Init.Prescaler         = cfg->prescaler;   // 预分频

    g_tim1_handle->Init.CounterMode  = TIM_COUNTERMODE_UP; // 边沿对齐模式 计数器向上计数
    if (cfg->level_logic)
        g_tim1_oc_handle->OCMode = TIM_OCMODE_PWM1; // PWM模式1 TIMx_CCMRx 高电平有效
    else
        g_tim1_oc_handle->OCMode = TIM_OCMODE_PWM2; // PWM模式2 TIMx_CCMRx 低电平有效
    __HAL_RCC_TIM1_CLK_ENABLE();
    /* Set TIMx instance */
    HAL_TIM_PWM_Init(g_tim1_handle);
    return 0;
}

void bsp_tim1_pwm_deinit(void) {
    if (!g_tim1_handle) return; // 未初始化
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_1);
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_2);
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_3);
    HAL_TIM_PWM_Stop(g_tim1_handle, TIM_CHANNEL_4);

    HAL_TIM_PWM_DeInit(g_tim1_handle);
    __HAL_RCC_TIM1_CLK_DISABLE();
    free(g_tim1_handle);
    g_tim1_handle = NULL;
    if (g_tim1_oc_handle) free(g_tim1_oc_handle);
    g_tim1_oc_handle = NULL;
}

/**
 * @brief  将指定PWM通道使能，单纯的初始化并不会使能通道
 * @param  ch: TIM_CHANNEL_1 ~ TIM_CHANNEL_4
 * @param  en: 0--关闭  1--使能
 */
void bsp_tim1_pwm_ch_en(uint8_t ch, uint8_t en) {
    if (!g_tim1_handle || !g_tim1_oc_handle) return; // 未初始化
    switch (ch) {
        case TIM_CHANNEL_1:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_1);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_1, en);
            break;
        case TIM_CHANNEL_2:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_2);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_2, en);
            break;
        case TIM_CHANNEL_3:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_3);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_3, en);
            break;
        case TIM_CHANNEL_4:
            HAL_TIM_PWM_ConfigChannel(g_tim1_handle, g_tim1_oc_handle, TIM_CHANNEL_4);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim1_handle->Instance, TIM_CHANNEL_4, en);
            break;
        default:
            break;
    }
}

void bsp_tim1_drive_pwm_init(uint8_t io_ch1, uint8_t io_ch2,
                             uint8_t io_ch3, uint8_t io_ch4) {
    if ((io_ch1 == 0 || (io_ch1 > LS_IO_NUM - 1)) &&
        (io_ch2 == 0 || (io_ch2 > LS_IO_NUM - 1)) &&
        (io_ch3 == 0 || (io_ch3 > LS_IO_NUM - 1)) &&
        (io_ch4 == 0 || (io_ch4 > LS_IO_NUM - 1))) {
        bsp_tim1_pwm_deinit();
        return;
    }
    io_cfg_as_tim(io_ch1, GPIO_AF1_TIM1_CH1);
    io_cfg_as_tim(io_ch2, GPIO_AF1_TIM1_CH2);
    io_cfg_as_tim(io_ch3, GPIO_AF1_TIM1_CH3);
    io_cfg_as_tim(io_ch4, GPIO_AF1_TIM1_CH4);
    uint8_t ret = bsp_tim1_pwm_init(&g_tim1_cfg);
    if (!ret) {
        if (io_ch1 > 0 && (io_ch1 < LS_IO_NUM) && g_io_cfg[io_ch1].type == IO_TYPE_TIM1_CH1)
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_1, 1);
        else
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_1, 0);

        if (io_ch2 > 0 && (io_ch2 < LS_IO_NUM) && g_io_cfg[io_ch2].type == IO_TYPE_TIM1_CH2)
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_2, 1);
        else
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_2, 0);

        if (io_ch3 > 0 && (io_ch3 < LS_IO_NUM) && g_io_cfg[io_ch3].type == IO_TYPE_TIM1_CH3)
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_3, 1);
        else
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_3, 0);

        if (io_ch4 > 0 && (io_ch4 < LS_IO_NUM) && g_io_cfg[io_ch4].type == IO_TYPE_TIM1_CH4)
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_4, 1);
        else
            bsp_tim1_pwm_ch_en(TIM_CHANNEL_4, 0);
    } else {
        LOGE("tim1 pwm init fail.%d", ret);
    }
}
#endif

#if LS_TIM2_EN
uint8_t bsp_tim2_pwm_init(bsp_tim_cfg_t *cfg) {
    if (g_tim2_handle) return 0; // 已经初始化过
    if (cfg == NULL) return 3; // 配置为空
    g_tim2_handle = malloc(sizeof(TIM_HandleTypeDef)); // 申请空间
    if (!g_tim2_handle) return 1; // TIM结构体无法申请空间
    g_tim2_oc_handle = malloc(sizeof(TIM_OC_InitTypeDef)); // 申请空间
    if (!g_tim2_oc_handle) {
        free(g_tim2_handle);
        return 2; // TIM类型结构体无法申请空间
    }
    // 结构体赋值
    g_tim2_handle->Instance               = TIM2;
    g_tim2_handle->Init.ClockDivision     = 0;                              // CKD 时钟分频因子(Clock division)
    g_tim2_handle->Init.RepetitionCounter = 0;                              // TIM2_RCR 重复计数器的值
    g_tim2_handle->Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; // 禁止自动重装载

    g_tim2_handle->Init.Period            = cfg->period;                 // 重装载值
    g_tim2_handle->Init.Prescaler         = cfg->prescaler;              // 预分频
    g_tim2_handle->Init.CounterMode       = TIM_COUNTERMODE_UP; // 边沿对齐模式 计数器向上计数
    if (cfg->level_logic)
        g_tim2_oc_handle->OCMode = TIM_OCMODE_PWM1; // PWM模式1 TIMx_CCMRx 高电平有效
    else
        g_tim2_oc_handle->OCMode = TIM_OCMODE_PWM2; // PWM模式2 TIMx_CCMRx 低电平有效

    __HAL_RCC_TIM2_CLK_ENABLE();
    /* Set TIMx instance */
    HAL_TIM_PWM_Init(g_tim2_handle);
    return 0;
}

void bsp_tim2_pwm_deinit(void) {
    if (!g_tim2_handle) return; // 未初始化

    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_1);
    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_2);
    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_3);
    HAL_TIM_PWM_Stop(g_tim2_handle, TIM_CHANNEL_4);

    HAL_TIM_PWM_DeInit(g_tim2_handle);
    __HAL_RCC_TIM2_CLK_DISABLE();
    free(g_tim2_handle);
    g_tim2_handle = NULL;
    if (g_tim2_oc_handle) free(g_tim2_oc_handle);
    g_tim2_oc_handle = NULL;
}

void bsp_tim2_drive_pwm_init(uint8_t io_ch1, uint8_t io_ch2,
                             uint8_t io_ch3, uint8_t io_ch4) {
    if ((io_ch1 == 0 || (io_ch1 > LS_IO_NUM - 1)) &&
        (io_ch2 == 0 || (io_ch2 > LS_IO_NUM - 1)) &&
        (io_ch3 == 0 || (io_ch3 > LS_IO_NUM - 1)) &&
        (io_ch4 == 0 || (io_ch4 > LS_IO_NUM - 1))) {
        bsp_tim2_pwm_deinit();
        return;
    }
    io_cfg_as_tim(io_ch1, GPIO_AF8_TIM2_CH1);
    io_cfg_as_tim(io_ch2, GPIO_AF8_TIM2_CH2);
    io_cfg_as_tim(io_ch3, GPIO_AF8_TIM2_CH3);
    io_cfg_as_tim(io_ch4, GPIO_AF8_TIM2_CH4);
    uint8_t ret = bsp_tim2_pwm_init(&g_tim2_cfg);
    if (!ret) {
        if (io_ch1 > 0 && (io_ch1 < LS_IO_NUM) && g_io_cfg[io_ch1].type == IO_TYPE_TIM2_CH1)
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_1, 1);
        else
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_1, 0);

        if (io_ch2 > 0 && (io_ch2 < LS_IO_NUM) && g_io_cfg[io_ch2].type == IO_TYPE_TIM2_CH2)
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_2, 1);
        else
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_2, 0);

        if (io_ch3 > 0 && (io_ch3 < LS_IO_NUM) && g_io_cfg[io_ch3].type == IO_TYPE_TIM2_CH3)
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_3, 1);
        else
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_3, 0);

        if (io_ch4 > 0 && (io_ch4 < LS_IO_NUM) && g_io_cfg[io_ch4].type == IO_TYPE_TIM2_CH4)
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_4, 1);
        else
            bsp_tim2_pwm_ch_en(TIM_CHANNEL_4, 0);

    } else {
        LOGE("tim2 pwm init fail.%d", ret);
    }
}

/**
 * @brief  将指定PWM通道使能，单纯的初始化并不会使能通道
 * @param  ch: TIM_CHANNEL_1 ~ TIM_CHANNEL_4
 * @param  en: 0--关闭  1--使能
 */
void bsp_tim2_pwm_ch_en(uint8_t ch, uint8_t en) {
    if (!g_tim2_handle || !g_tim2_oc_handle)
        return; // 未初始化
    switch (ch) {
        case TIM_CHANNEL_1:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_1);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_1, en);
            break;
        case TIM_CHANNEL_2:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_2);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_2, en);
            break;
        case TIM_CHANNEL_3:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_3);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_3, en);
            break;
        case TIM_CHANNEL_4:
            HAL_TIM_PWM_ConfigChannel(g_tim2_handle, (TIM_OC_InitTypeDef *)g_tim2_oc_handle, TIM_CHANNEL_4);
            /* Enable the Capture compare channel */
            TIM_CCxChannelCmd(g_tim2_handle->Instance, TIM_CHANNEL_4, en);
            break;
        default:
            break;
    }
}
#endif

#if LS_TIM10_EN
/**
 * @brief  TIM10初始化
 * @param  *cfg: 基础定时器配置
 * @retval 0--成功  1--TIM结构体无法申请空间  2--配置为空
 */
uint8_t bsp_tim10_init(bsp_base_tim_cfg_t *cfg) {
    if (g_tim10_handle) return 0; // 已经初始化过
    if (cfg == NULL) return 2; // 配置为空
    g_tim10_handle = malloc(sizeof(BASETIM_HandleTypeDef)); // 申请空间
    if (!g_tim10_handle) return 1; // TIM结构体无法申请空间
    memset(g_tim10_handle, 0, sizeof(BASETIM_HandleTypeDef));
    // 结构体赋值
    g_tim10_handle->Instance          = TIM10;
    g_tim10_handle->Init.CntTimSel    = BASETIM_TIMER_SELECT;          // CKD 时钟分频因子(Clock division)
    g_tim10_handle->Init.MaxCntLevel  = BASETIM_MAXCNTLEVEL_16BIT;     // TimerSize=0：max count value=0xFFFF;
    g_tim10_handle->Init.AutoReload   = BASETIM_AUTORELOAD_ENABLE; // 模式2自动重装载计数器/定时器
    if (cfg->mode == 0)
        g_tim10_handle->Init.OneShot  = BASETIM_ONESHOT_MODE; // 单次模式
    else
        g_tim10_handle->Init.OneShot  = BASETIM_REPEAT_MODE; // 重复模式
    g_tim10_handle->Init.Prescaler    = cfg->prescaler;   // 预分频 cfg->prescaler
    g_tim10_handle->Init.Period       = BASETIM_MAXCNTVALUE_16BIT - HAL_RCC_GetPCLKFreq()/cfg->freq;  // 重装载值 cfg->period

    g_tim10_cfg = cfg;
    __HAL_RCC_BASETIM_CLK_ENABLE();
	HAL_BASETIM_Base_Init(g_tim10_handle);
    HAL_NVIC_SetPriority(TIM10_IRQn, cfg->priority);
	HAL_NVIC_EnableIRQ(TIM10_IRQn);
    return 0;
}

void bsp_tim10_set_pwm(uint8_t io, uint8_t val) {
    if (g_tim10_cfg == NULL || g_tim10_cfg->type != 1) return;
    HAL_BASETIM_Base_Stop_IT(g_tim10_handle);
    if (g_tim10_cfg->func.pwm.io != io) {
        g_tim10_cfg->func.pwm.io = io;
    }
    if (g_tim10_cfg->func.pwm.cnt != val) {
        g_tim10_cfg->func.pwm.cnt = val;
    }
    if (io != 0xff) {
        HAL_BASETIM_Base_Start_IT(g_tim10_handle);
    }
}

void bsp_tim10_start(void) {
    if (g_tim10_cfg == NULL) return;
    HAL_BASETIM_Base_Start_IT(g_tim10_handle);
}

void bsp_tim10_stop(void) {
    if (g_tim10_cfg == NULL) return;
    HAL_BASETIM_Base_Stop_IT(g_tim10_handle);
}

void TIM10_IRQHandler(void) {
    /* TIM Update event */
    if (__HAL_BASETIM_GET_FLAG(g_tim10_handle) != RESET) {
        if (__HAL_BASETIM_GET_IT_SOURCE(g_tim10_handle) != RESET) {
            __HAL_BASETIM_CLEAR_IT(g_tim10_handle);
            if (g_tim10_cfg == NULL) return;
            if (g_tim10_cfg->type == 1) {
                if (g_tim10_cfg->func.pwm.io == 0xFF) {
                    HAL_BASETIM_Base_Stop_IT(g_tim10_handle);
                    return;
                }

                if (g_tim10_pwm_update_cnt++ < g_tim10_cfg->func.pwm.cnt) {
                    io_out(g_tim10_cfg->func.pwm.io, IO_HIGH);
                } else if (g_tim10_pwm_update_cnt < g_tim10_cfg->freq - g_tim10_cfg->func.pwm.cnt) {
                    io_out(g_tim10_cfg->func.pwm.io, IO_LOW);
                } else {
                    g_tim10_pwm_update_cnt = 0;
                }
            } else if (g_tim10_cfg->type == 0) {
                if (g_tim10_cfg->func.tim.cb != NULL)
                    g_tim10_cfg->func.tim.cb();
            }
        }
    }
}
#endif

#if LS_TIM11_EN
/**
 * @brief  TIM11初始化
 * @param  *cfg: 基础定时器配置
 * @retval 0--成功  1--TIM结构体无法申请空间  2--配置为空
 */
uint8_t bsp_tim11_init(bsp_base_tim_cfg_t *cfg) {
    if (g_tim11_handle) return 0; // 已经初始化过
    if (cfg == NULL) return 2; // 配置为空
    g_tim11_handle = malloc(sizeof(BASETIM_HandleTypeDef)); // 申请空间
    if (!g_tim11_handle) return 1; // TIM结构体无法申请空间
    memset(g_tim11_handle, 0, sizeof(BASETIM_HandleTypeDef));
    // 结构体赋值
    g_tim11_handle->Instance          = TIM11;
    g_tim11_handle->Init.CntTimSel    = BASETIM_TIMER_SELECT;          // CKD 时钟分频因子(Clock division)
    g_tim11_handle->Init.MaxCntLevel  = BASETIM_MAXCNTLEVEL_16BIT;     // TimerSize=0：max count value=0xFFFF;
    g_tim11_handle->Init.AutoReload   = BASETIM_AUTORELOAD_ENABLE; // 模式2自动重装载计数器/定时器
    if (cfg->mode == 0)
        g_tim11_handle->Init.OneShot  = BASETIM_ONESHOT_MODE; // 单次模式
    else
        g_tim11_handle->Init.OneShot  = BASETIM_REPEAT_MODE; // 重复模式
    g_tim11_handle->Init.Prescaler    = cfg->prescaler;   // 预分频 cfg->prescaler
    g_tim11_handle->Init.Period       = BASETIM_MAXCNTVALUE_16BIT - HAL_RCC_GetPCLKFreq()/cfg->freq;  // 重装载值 cfg->period

    g_tim11_cfg = cfg;
    __HAL_RCC_BASETIM_CLK_ENABLE();
	HAL_BASETIM_Base_Init(g_tim11_handle);
    HAL_NVIC_SetPriority(TIM11_IRQn, cfg->priority);
	HAL_NVIC_EnableIRQ(TIM11_IRQn);
    return 0;
}

void bsp_tim11_set_pwm(uint8_t io, uint8_t val) {
    if (g_tim11_cfg == NULL || g_tim11_cfg->type != 1) return;
    HAL_BASETIM_Base_Stop_IT(g_tim11_handle);
    if (g_tim11_cfg->func.pwm.io != io) {
        g_tim11_cfg->func.pwm.io = io;
    }
    if (g_tim11_cfg->func.pwm.cnt != val) {
        g_tim11_cfg->func.pwm.cnt = val;
    }
    if (io != 0xff) {
        HAL_BASETIM_Base_Start_IT(g_tim11_handle);
    }
}

void TIM11_IRQHandler(void) {
    /* TIM Update event */
    if (__HAL_BASETIM_GET_FLAG(g_tim11_handle) != RESET) {
        if (__HAL_BASETIM_GET_IT_SOURCE(g_tim11_handle) != RESET) {
            __HAL_BASETIM_CLEAR_IT(g_tim11_handle);
            if (g_tim11_cfg == NULL) return;
            if (g_tim11_cfg->type == 1) {
                if (g_tim11_cfg->func.pwm.io == 0xFF) {
                    HAL_BASETIM_Base_Stop_IT(g_tim11_handle);
                    return;
                }

                if (g_tim11_pwm_update_cnt++ < g_tim11_cfg->func.pwm.cnt) {
                    io_out(g_tim11_cfg->func.pwm.io, IO_HIGH);
                } else if (g_tim11_pwm_update_cnt < g_tim11_cfg->freq - g_tim11_cfg->func.pwm.cnt) {
                    io_out(g_tim11_cfg->func.pwm.io, IO_LOW);
                } else {
                    g_tim11_pwm_update_cnt = 0;
                }

            } else if (g_tim11_cfg->type == 0) {
                if (g_tim11_cfg->func.tim.cb != NULL)
                    g_tim11_cfg->func.tim.cb();
            }
        }
    }
}

void bsp_tim11_start(void) {
    if (g_tim11_cfg == NULL) return;
    HAL_BASETIM_Base_Start_IT(g_tim11_handle);
}

void bsp_tim11_stop(void) {
    if (g_tim11_cfg == NULL) return;
    HAL_BASETIM_Base_Stop_IT(g_tim11_handle);
}
#endif
